#include "mainwidget.h"
#include "ui_mainwidget.h"
#include "webview.h"
#include <QtWebKit>
#include "t_youtube_dump_lib.h"

//#define USE_MP4_COPY (1)
#define USE_MP4_COPY (0)

MainWidget::MainWidget(QWidget *parent, MainApplication *app) :
    QWidget(parent)
    ,ui(new Ui::MainWidget)
    ,f_app(app)
{
    ui->setupUi(this);

    //this->setWindowTitle(f_app->f_video_id);
    this->setWindowTitle(QString("ダウンロード: ") + f_app->f_video_info.f_title);
    this->setWindowFlags(
                Qt::WindowStaysOnTopHint
                //| Qt::FramelessWindowHint
                );
    //this->setWindowFlags(Qt::WindowStaysOnTopHint);

    f_web_view = new WebView(this);
    f_web_view->setObjectName(QString::fromUtf8("webView_1"));
    f_web_view->setUrl(QUrl("about:blank"));
    ui->horizontalLayout->addWidget(f_web_view);

    Q_ASSERT(app);
    f_app = app;

    f_web_view->page()->setNetworkAccessManager(&f_app->f_nam);
    f_web_view->setContextMenuPolicy(Qt::NoContextMenu);

    populateJavaScriptWindowObject();
    connect(f_web_view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
            this, SLOT(populateJavaScriptWindowObject()));

    ui->pushButton->setText("閉じる");

    this->resize(600, 300);

    // [HTML初期化]

    Q_ASSERT(f_app);
    if(!f_app->f_status)
    {
        qDebug() << "[on_pushButton_clicked]: (!f_app->f_status)";
        return;
    }

    foreach(int v_fmt, f_app->f_video_info.f_fmt_map.keys())
    {
        if(
                ////v_fmt != 5 &&
                v_fmt != 18
                && v_fmt != 22
                && v_fmt != 34
                && v_fmt != 35
                && v_fmt != 37
                )
        {
            f_app->f_video_info.f_fmt_map.remove(v_fmt);
        }
    }

    foreach(int v_fmt, f_app->f_video_info.f_fmt_map.keys())
    {
        QUrl v_url = f_app->f_video_info.f_fmt_map.value(v_fmt);
        if(v_url.isValid())
        {
            QString v_removed_url = QUrl::fromPercentEncoding(v_url.toString().toLatin1());
            qDebug() << "[v_fmt, v_removed_url]" << v_fmt << v_removed_url;
            qDebug() << "";
        }
    }

    qDebug() << "[v_error_list]" << f_app->f_video_info.f_error_list;
    if(f_app->f_video_info.f_error_list.size()>0)
    {
        qDebug() << "v_error_list.last()" << f_app->f_video_info.f_error_list.last();

    }

    QString v_html = "";
    v_html += QString("ダウンロードするファイル形式を選んでください。<br />");
    foreach(int v_fmt, f_app->f_video_info.f_fmt_map.keys())
    {
        v_html += QString(" <button onclick='widget1.submitIdToDownload(\"%1\",%2, \"bin\")'>fmt=%2(%3)</button>")
                .arg(f_app->f_video_id).arg(v_fmt).arg(f_app->f_video_info.f_fmt_size_map.value(v_fmt));
    }
    v_html += "<br />\n";
    v_html += QString(" <button onclick='widget1.submitIdToDownload(\"%1\", 18, \"mp3\")'>MP3(18)</button>")
              .arg(f_app->f_video_id);
    v_html += QString(" <button onclick='widget1.submitIdToDownload(\"%1\", 34, \"mp3\")'>MP3(34)</button>")
              .arg(f_app->f_video_id);
    v_html += "<br />\n";
    v_html += QString(" <button onclick='widget1.submitIdToDownload(\"%1\", 18, \"m4a\")'>AAC(18)</button>")
              .arg(f_app->f_video_id);
    v_html += QString(" <button onclick='widget1.submitIdToDownload(\"%1\", 34, \"m4a\")'>AAC(34)</button>")
              .arg(f_app->f_video_id);
    v_html += "<br />\n";
    v_html += QString("<center>");
    for(int i=0; i<3; i++)
    {
        QString v_img_url = QString("http://i.ytimg.com/vi/%1/%2.jpg").arg(f_app->f_video_id).arg(i+1);
        v_html += QString("<img src='%1' />").arg(v_img_url);
    }
    v_html += QString("</center>");
    qDebug() << "[v_html]" << v_html;
    ////ui->webView->setHtml(v_html);
    f_web_view->setHtml(v_html);
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::populateJavaScriptWindowObject()
{
    qDebug() << "[MainWidget::populateJavaScriptWindowObject()]";
    f_web_view->page()->mainFrame()->addToJavaScriptWindowObject("widget1", this);
}

void MainWidget::on_pushButton_clicked()
{
    qApp->quit();
}

bool MainWidget::setXmlContent(QDomDocument &domDocument, QByteArray &rawXml)
{
    QBuffer v_in;
    v_in.setBuffer(&rawXml);
    QString v_errorStr;
    int v_errorLine;
    int v_errorColumn;
    if (!domDocument.setContent(
            &v_in,
            true,
            &v_errorStr,
            &v_errorLine,
            &v_errorColumn))
    {
        qDebug() << qApp->tr("Parse error at line %1, column %2:\n%3")
               .arg(v_errorLine)
               .arg(v_errorColumn)
               .arg(v_errorStr);
        qDebug() << "[rawXml]" << rawXml;
        return false;
    }
    return true;
}

QString MainWidget::getVideoTitle(QString a_id)
{
#if 0x0
    QString v_url_str = QString("http://gdata.youtube.com/feeds/api/videos/%1").arg(a_id);
    T_NetworkBatch v_nbat(&f_app->f_nam);
    QNetworkReply *v_reply = v_nbat.get(v_url_str);
    QByteArray v_result = v_reply->readAll();
    qDebug() << "[v_result]" << v_result;
    v_reply->deleteLater();
    QDomDocument domDocument;
    if(!setXmlContent(domDocument, v_result))
    {
        qDebug() << "xml parse error!";
        return "";
    }
    // [/entry]
    QDomElement v_entry = domDocument.documentElement();
    // [/entry/title]
    QDomElement v_title = v_entry.elementsByTagNameNS("http://www.w3.org/2005/Atom", "title")
                                .at(0).toElement();
    QString v_video_title = v_title.text();
#else
    QString v_video_title = f_app->f_video_info.f_title;
#endif

    qDebug() << "[v_video_title](1)" << v_video_title;
    // /\:*?"<>|#{}%&~
    v_video_title.replace("/", "／");
    v_video_title.replace("\\", "￥");
    v_video_title.replace(":", "：");
    v_video_title.replace("*", "＊");
    v_video_title.replace("?", "？");
    v_video_title.replace("\"", "”");
    v_video_title.replace("<", "＜");
    v_video_title.replace(">", "＞");
    v_video_title.replace("|", "｜");
    v_video_title.replace("#", "＃");
    v_video_title.replace("{", "｛");
    v_video_title.replace("}", "｝");
    v_video_title.replace("%", "％");
    v_video_title.replace("&", "＆");
    v_video_title.replace("~", "～");
    qDebug() << "[v_video_title](2)" << v_video_title;
    QByteArray v_video_title_local8 = v_video_title.toLocal8Bit();
    v_video_title = QString::fromLocal8Bit(v_video_title_local8);
    v_video_title.replace("?", "-");
    qDebug() << "[v_video_title](3)" << v_video_title;
    return v_video_title;
}

QString MainWidget::getSaveFileName(QString a_title, QString a_id, int a_fmt, QString a_type)
{
    if(a_fmt < 0) a_fmt = -a_fmt;
    QSettings v_settings(
            QSettings::IniFormat, //QSettings::NativeFormat,
            QSettings::UserScope, // QSettings::SystemScope,
            QCoreApplication::organizationName(),
            QCoreApplication::applicationName()
            );
    QString v_saveDir = v_settings.value("Dirs/saveDirectory", "").toString();
    if(v_saveDir.isEmpty())
    {
        v_saveDir = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
    }
    QDir v_dir(v_saveDir);
    QString v_file_base = v_dir.filePath(a_title + " - " + QString("%1 (fmt=%2)").arg(a_id).arg(a_fmt<0 ? -a_fmt : a_fmt));
    QMap<int, QString> v_suffix_map;
    if(a_type=="mp3")
    {
        v_suffix_map.insert(5, "mp3");
        v_suffix_map.insert(18, "mp3");
        v_suffix_map.insert(22, "mp3");
        v_suffix_map.insert(34, "mp3");
        v_suffix_map.insert(35, "mp3");
        v_suffix_map.insert(37, "mp3");
    }
    else if(a_type=="m4a")
    {
        v_suffix_map.insert(5, "m4a");
        v_suffix_map.insert(18, "m4a");
        v_suffix_map.insert(22, "m4a");
        v_suffix_map.insert(34, "m4a");
        v_suffix_map.insert(35, "m4a");
        v_suffix_map.insert(37, "m4a");
    }
    else
    {
        v_suffix_map.insert(5, "flv");
        v_suffix_map.insert(18, "mp4");
        v_suffix_map.insert(22, "mp4");
        v_suffix_map.insert(34, "flv");
        v_suffix_map.insert(35, "flv");
        v_suffix_map.insert(37, "mp4");
    }
    QString v_file_sfx = v_suffix_map.value(a_fmt, "bin");
    QString v_file_name = v_file_base + "." + v_file_sfx;

    QFileDialog v_dialog(this);
    v_dialog.setWindowTitle("ダウンロード先ファイルの指定");
    v_dialog.setAcceptMode(QFileDialog::AcceptSave);
    v_dialog.setNameFilter(tr("Movies (*.mp3 *.m4a *.flv *.mp4)"));
    v_dialog.selectFile(v_file_name);
    QStringList fileNames;
    if (!v_dialog.exec())
    {
        return "";
    }
    fileNames = v_dialog.selectedFiles();
    QString v_dl_file_name = fileNames.at(0);
    QFileInfo v_dl_file_info(v_dl_file_name);
    v_settings.setValue("Dirs/saveDirectory", v_dl_file_info.dir().absolutePath());

    // サフィックスが期待値と異なる場合、期待値を追加
    QString v_file_suffix = v_dl_file_info.suffix();
    if(v_file_suffix.toLower() != v_file_sfx)
    {
        v_dl_file_name += "."+v_file_sfx;
    }

    return v_dl_file_name;
}


void MainWidget::submitIdToDownload(QString a_id, int a_fmt, QString a_type)
{
    qDebug() << "[MainWidget::submitIdToDownload()]" << a_id << a_fmt;

    // ビデオのタイトルを取得する
    QString v_video_title = getVideoTitle(a_id);

    QString v_dl_file_path = this->getSaveFileName(v_video_title, a_id, a_fmt, a_type);
    if(v_dl_file_path.isEmpty()) return;

    ////ui->progressBar->setValue(0);
    Q_ASSERT(a_fmt >= 0);
    // 全体のファイルサイズとコンテントタイプを取得
    QUrl v_encoded_url;
    v_encoded_url = f_app->f_video_info.f_fmt_map.value(a_fmt);
    QUrl v_removed_url = QUrl::fromPercentEncoding(v_encoded_url.toString().toLatin1());

    // テンポラリ・バッチファイルを作成する
    QString v_temp_loc = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
    qDebug() << "[v_temp_loc]" << v_temp_loc;
    QFile v_dl_bat;
    for(int i=0; true; i++)
    {
        v_dl_bat.setFileName(v_temp_loc + "/~" + QCoreApplication::applicationName() + "~" + QString::number(i)+".bat");
        if(v_dl_bat.exists())
        {
            QFileInfo v_temp_info(v_dl_bat);
            //QDateTime v_temp_c_dt = v_temp_info.created();
            QDateTime v_temp_c_dt = v_temp_info.lastModified();
            QDateTime v_now_dt = QDateTime::currentDateTime ();
            if(v_temp_c_dt.secsTo(v_now_dt) > (3600 * 24))
            {
                if(v_dl_bat.remove())
                {
                    break;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                continue;
            }
        }
        else
        {
            break;
        }
    }

    if(!v_dl_bat.open(QIODevice::WriteOnly))
    {
        return;
    }
    QString v_watch_url = QString("http://www.youtube.com/watch?v=%1").arg(a_id);
    QString v_dl_bat_native = QDir::toNativeSeparators(v_dl_bat.fileName());
    QString v_dl_bat_cont; // batch content
    QFile v_removed_file(v_dl_file_path);
    if(v_removed_file.exists())
    {
        if(!v_removed_file.remove())
        {
            QMessageBox::information(this, "title", "remove() failed");
        }
    }
    QString v_curl = T_Youtube_Dump_Lib::getToolsExe("curl", true);
    QString v_ffmpeg = T_Youtube_Dump_Lib::getToolsExe("ffmpeg", true);
    QString v_lame = T_Youtube_Dump_Lib::getToolsExe("lame", true);
    qDebug() << "[v_ffmpeg]" << v_ffmpeg;
    if(a_type == "mp3")
    {
        // Generate MP3
        //QString v_mp3_opt = "-m j -q 0 --vbr-new -V 2 --lowpass -1 --highpass -1";
        //QString v_mp3_opt = "-m j -q 0 -V 2 --lowpass -1 --highpass -1";
        //QString v_mp3_opt = "-m j -q 0 -V 2";
        //QString v_mp3_opt = "-m j -q 0 -V 4";
        QString v_mp3_opt = "-m j -q 0 -b 128";
        v_dl_bat_cont += QString("%1 ").arg(v_curl);
        v_dl_bat_cont += QString("\"%1\"").arg(v_removed_url.toString());
        v_dl_bat_cont += (" | ");
        v_dl_bat_cont += QString("%1 ").arg(v_ffmpeg);
        v_dl_bat_cont += (" -y -i pipe:0 -f wav -- pipe:1 2>NUL | ");
        v_dl_bat_cont += QString("lame %1 ").arg(v_lame);
        v_dl_bat_cont += QString(" %2 --ta \"%1\" --tl \"%2\" - ")
                .arg(v_watch_url)
                .arg(v_mp3_opt)
                ;
#if 0x1
        v_dl_bat_cont += ("\"");
        v_dl_bat_cont += QDir::toNativeSeparators(v_dl_file_path);
        v_dl_bat_cont += ("\" 2>NUL");
#else
        v_dl_bat_cont += (" - > ");
        v_dl_bat_cont += ("\"");
        v_dl_bat_cont += QDir::toNativeSeparators(v_dl_file_path);
        v_dl_bat_cont += ("\" 2>NUL");
#endif
        ////v_dl_bat_cont += ("\r\n");
        v_dl_bat_cont += (" & ");
        ////v_dl_bat_cont += ("@echo off\r\n");
        v_dl_bat_cont += ("@echo off");
        v_dl_bat_cont += (" & ");
        ////v_dl_bat_cont += ("echo ダウンロード処理が終了しました\r\n");
        v_dl_bat_cont += ("echo ダウンロード処理が終了しました");
        v_dl_bat_cont += (" & ");
        v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & pause & exit\r\n");
        ////v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & pause & exit");
        v_dl_bat.write(v_dl_bat_cont.toLocal8Bit());
    }
    else if(a_type == "m4a")
    {
        // Generate M4A
        v_dl_bat_cont += QString("%1 ").arg(v_curl);
        v_dl_bat_cont += QString("\"%1\"").arg(v_removed_url.toString());
        v_dl_bat_cont += (" | ");
        v_dl_bat_cont += QString("%1 ").arg(v_ffmpeg);
#if 0x1
        v_dl_bat_cont += QString(" -y -i pipe:0 -vn -acodec copy -metadata artist=\"%1\" -f mp4 -- \"%2\" 2>NUL ")
                .arg(v_watch_url).arg(QDir::toNativeSeparators(v_dl_file_path));
#else
        v_dl_bat_cont += QString(" -y -i pipe:0 -vn -acodec copy -f mp4 -- pipe:1 > \"%1\" 2>NUL ")
                .arg(QDir::toNativeSeparators(v_dl_file_path));
#endif
        v_dl_bat_cont += ("\r\n");
        v_dl_bat_cont += ("@echo off\r\n");
        v_dl_bat_cont += ("echo ダウンロード処理が終了しました\r\n");
        v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & pause & exit\r\n");
        v_dl_bat.write(v_dl_bat_cont.toLocal8Bit());
    }
    else
    {
        // Movie Copy
        QString v_stream_exe = getStreamExe();
#if 0x1
        v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & ");
        v_dl_bat_cont += QString("%1 ").arg(v_stream_exe);
        v_dl_bat_cont += (" \"");
        v_dl_bat_cont += a_id;
        v_dl_bat_cont += ("\" ");
        v_dl_bat_cont += QString("%1").arg(a_fmt);
        v_dl_bat_cont += (" ");
        v_dl_bat_cont += ("100");
        v_dl_bat_cont += (" > ");
        v_dl_bat_cont += (" \"");
        v_dl_bat_cont += QDir::toNativeSeparators(v_dl_file_path);
        v_dl_bat_cont += ("\" ");
        v_dl_bat_cont += (" & ");
        v_dl_bat_cont += ("@echo off & ");
        v_dl_bat_cont += ("echo ダウンロード処理が終了しました & ");
        //v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & pause & exit\r\n");
        v_dl_bat_cont += ("pause & exit\r\n");
        v_dl_bat.write(v_dl_bat_cont.toLocal8Bit());
        //QProcess::startDetached(v_dl_bat_cont);
        //this->close();
        //system(v_dl_bat_cont.toLocal8Bit().constData());
#else
        v_dl_bat_cont += QString("%1 ").arg(v_curl);
        v_dl_bat_cont += (" -o \"");
        v_dl_bat_cont += QDir::toNativeSeparators(v_dl_file_path);
        v_dl_bat_cont += ("\" ");
        v_dl_bat_cont += QString("\"%1\"").arg(v_removed_url.toString());
        v_dl_bat_cont += ("\r\n");
        v_dl_bat_cont += ("@echo off\r\n");
        v_dl_bat_cont += ("echo ダウンロード処理が終了しました\r\n");
        v_dl_bat_cont += ("del /F \"%~dp0%~nx0\" & pause & exit\r\n");
        v_dl_bat.write(v_dl_bat_cont.toLocal8Bit());
#endif
    }
    v_dl_bat.close();

    qDebug() << "[v_dl_bat_native]" << v_dl_bat_native;
    QString v_cmd_line = QString("start \"ダウンロード中: %1\"").arg(v_video_title)+ QString(" \"%1\"").arg(v_dl_bat_native);
    system(v_cmd_line.toLocal8Bit());
    qApp->quit();
}

QString MainWidget::getStreamExe()
{
    QString v_app_dir_path = QCoreApplication::applicationDirPath();
    qDebug() << "[QCoreApplication::applicationDirPath]" << v_app_dir_path;
    QString v_dl_exe_path = v_app_dir_path + "/yt_stream.exe";
    if(QFileInfo(v_dl_exe_path).exists())
    {
        return v_dl_exe_path;
    }
    return "C:/usr/local/release/yt_stream.exe";
}

